package com.gopay.bis.manager.bank.cbrmb;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.cipher.utils.LoggerMaskUtils;
import com.gopay.common.constants.cbrmb.CbRmbBankConstants;
import com.gopay.common.constants.cbrmb.CbRmbBankOrderState;
import com.gopay.common.constants.cbrmb.CbRmbOrderState;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.dao.cbrmb.CbRmbBankMessageDtlDao;
import com.gopay.common.cps.dao.cbrmb.CbRmbBankOrderDtlDao;
import com.gopay.common.cps.dao.cbrmb.CbRmbBankOrderMessageRelDao;
import com.gopay.common.cps.dao.cbrmb.CbRmbTranAssistDtlDao;
import com.gopay.common.cps.dao.cbrmb.CbRmbTranAssistDtlLogDao;
import com.gopay.common.domain.bank.ccb.cbrmb.CbRmbXmlFile;
import com.gopay.common.domain.bank.ccb.cbrmb.CbRmbXmlFileHead;
import com.gopay.common.domain.bank.ccb.cbrmb.req.CbRmbNotificationMsg;
import com.gopay.common.domain.bank.ccb.cbrmb.req.CbRmbQueryReqMsg;
import com.gopay.common.domain.bank.ccb.cbrmb.res.CbRmbQueryRespMsg;
import com.gopay.common.domain.bank.ccb.cbrmb.res.CbRmbResponseMsg;
import com.gopay.common.domain.cbrmb.CbRmbBankMessageDtl;
import com.gopay.common.domain.cbrmb.CbRmbBankOrderDtl;
import com.gopay.common.domain.cbrmb.CbRmbBankOrderMessageRel;
import com.gopay.common.domain.cbrmb.CbRmbTranAssistDtl;
import com.gopay.common.domain.cbrmb.CbRmbTranAssistDtlLog;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.cbrmb.BeanMapper;
import com.gopay.common.util.cbrmb.FtpUtils;
import com.gopay.remote.bank.cbrmb.CbRmbCcbBankRemoteService;
import com.gopay.remote.cps.cbrmb.CbrmbBankCallbackRemoteService;

public class CbRmbCcbBankManager implements CbRmbCcbBankRemoteService {

	private static final Logger logger = LoggerFactory.getLogger(CbRmbCcbBankManager.class);

	@Resource(name = "cbRmbCcbBankServiceClient")
	private CbRmbCcbBankRemoteService cbRmbCcbBankServiceClient;

	@Resource(name = "cbRmbBankOrderDtlDao")
	private CbRmbBankOrderDtlDao cbRmbBankOrderDtlDao;

	@Resource(name = "cbRmbBankOrderMessageRelDao")
	private CbRmbBankOrderMessageRelDao cbRmbBankOrderMessageRelDao;

	@Resource(name = "cbRmbBankMessageDtlDao")
	private CbRmbBankMessageDtlDao cbRmbBankMessageDtlDao;

	@Resource(name = "cbRmbTranAssistDtlDao")
	private CbRmbTranAssistDtlDao cbRmbTranAssistDtlDao;

	@Resource(name = "cbrmbBankCallbackClient")
	private CbrmbBankCallbackRemoteService cbrmbBankCallbackClient;

	@Resource(name = "cbRmbTranAssistDtlLogDao")
	private CbRmbTranAssistDtlLogDao cbRmbTranAssistDtlLogDao;

	@Resource(name = "cbrConfig")
	private Map<String, String> cbrConfig;

	@Override
	public CbRmbResponseMsg submit(CbRmbNotificationMsg msg) throws GopayException {
		logger.error("=========this is bis manager =============" + ReflectionToStringBuilder.toString(msg));
		return cbRmbCcbBankServiceClient.submit(msg);
	}

	@Override
	public String callBIS(CbRmbNotificationMsg notificationMsg, CbRmbResponseMsg responseMsg) throws GopayException {
		String respCode = "0000";
		logger.error("===this  is  bis===");
		try {
			CbRmbBankMessageDtl cbRmbBankMessageDtl = new CbRmbBankMessageDtl();
			BeanMapper.copy(notificationMsg, cbRmbBankMessageDtl);
			cbRmbBankMessageDtl.setRetCode(responseMsg.getRetCode());
			cbRmbBankMessageDtl.setRetMsg(responseMsg.getRetMsg());
			cbRmbBankMessageDtl.setCreateTime(new Date());
			cbRmbBankMessageDtl.setLastUpdateTime(new Date());
			cbRmbBankMessageDtlDao.save(cbRmbBankMessageDtl);
			String resXml = xmlFileToString(cbRmbBankMessageDtl.getFileName().trim());
			CbRmbXmlFile xmlFile = BeanMapper.toBean(resXml.replace(CbRmbBankConstants.XML_HEAD, ""),
					CbRmbXmlFile.class);
			List<CbRmbBankOrderDtl> cbRmbBankOrderDtls = BeanMapper.mapList(xmlFile.getCbRmbXmlFileBody(),
					CbRmbBankOrderDtl.class);
			int orderMessageId = 0;
			for (CbRmbBankOrderDtl order : cbRmbBankOrderDtls) {
				logger.error("*********回盘数据:xml文件数据_1："
						+ LoggerMaskUtils.maskString(ReflectionToStringBuilder.toString(order)));
				CbRmbBankOrderDtl orderDtl = cbRmbBankOrderDtlDao.findByGopayOrderId(order.getGopayOrderId());
				logger.error("*********回盘数据:local数据_1：" + orderDtl.getGopayOrderId());
				if (orderMessageId == 0) {
					orderMessageId = orderDtl.getOrderMessageId();
				}
				orderDtl.setFims_no(order.getFims_no());
				orderDtl.setBank_bus_no(order.getBank_bus_no());
				orderDtl.setBank_exchangerate(order.getBank_exchangerate());
				orderDtl.setBank_handling(order.getBank_handling());
				orderDtl.setBank_payamt(order.getBank_payamt());
				orderDtl.setBank_telegram(order.getBank_telegram());
				orderDtl.setReport_date(order.getReport_date());
				orderDtl.setReturn_code(order.getReturn_code());
				orderDtl.setReturn_info(order.getReturn_info());
				orderDtl.setRcpm_no(order.getRcpm_no());
				orderDtl.setState(CbRmbBankOrderState._03.value);
				orderDtl.setLastUpdateTime(new Date());
				cbRmbBankOrderDtlDao.update(orderDtl);
				CbRmbTranAssistDtl tranAssisDtl = cbRmbTranAssistDtlDao.findByGopayOrderId(order.getGopayOrderId());
				if (CbRmbBankConstants.PAY_SUCCESS.equals(orderDtl.getReturn_code())) {
					// 支付成功
					tranAssisDtl.setState(CbRmbOrderState.PAY_SUCCESS.value);
				} else {
					// 支付失败
					tranAssisDtl.setState(CbRmbOrderState.PAY_FAIL.value);
					CbRmbTranAssistDtlLog assistLog = new CbRmbTranAssistDtlLog();
					assistLog.setCreateTime(new Date());
					assistLog.setLastUpdateTime(new Date());
					assistLog.setGopayOrderId(order.getGopayOrderId());
					assistLog.setReturnCode(order.getReturn_code());
					assistLog.setReturnInfo(order.getReturn_info());
					assistLog.setTranType("2");// 0报盘,1回盘,2付款
					cbRmbTranAssistDtlLogDao.save(assistLog);
				}
				tranAssisDtl.setHpFinishTime(new Date());
				tranAssisDtl.setLastUpdateTime(new Date());
				cbRmbTranAssistDtlDao.update(tranAssisDtl);
			}
			cbRmbBankMessageDtl.setOrderMessageId(orderMessageId);
			cbRmbBankMessageDtl.setLastUpdateTime(new Date());
			cbRmbBankMessageDtlDao.update(cbRmbBankMessageDtl);
			logger.error("*****update orderMessageId=" + orderMessageId + ",CbRmbBankMessageDtl="
					+ cbRmbBankMessageDtl.getMessageId());
			CbRmbBankOrderMessageRel orderMessageRel = cbRmbBankOrderMessageRelDao.find(CbRmbBankOrderMessageRel.class,
					orderMessageId);
			logger.error("****" + ReflectionToStringBuilder.toString(orderMessageRel));
			CbRmbXmlFileHead xmlHead = xmlFile.getCbRmbXmlFileHead();
			orderMessageRel.setTotalpayamt(xmlHead.getTotalpayamt());
			orderMessageRel.setTotalhandling(xmlHead.getTotalhandling());
			orderMessageRel.setTotaltelegram(xmlHead.getTotaltelegram());
			orderMessageRel.setResXml(resXml);
			orderMessageRel.setLastUpdateTime(new Date());
			cbRmbBankOrderMessageRelDao.update(orderMessageRel);
			// 此处会调用cps做账，所以放在最后，防止cps出错后导致其他数据不全;
			for (CbRmbBankOrderDtl order : cbRmbBankOrderDtls) {
				logger.error(" cps 开始做账*****");
				CbRmbBankOrderDtl orderDtl = cbRmbBankOrderDtlDao.findByGopayOrderId(order.getGopayOrderId());
				if (CbRmbBankConstants.PAY_SUCCESS.equals(orderDtl.getReturn_code())) {
					// 支付成功
					cbrmbBankCallbackClient.bankReturnFinishOrder(orderDtl);
					logger.error(" cps 做账完成");
				}

			}
			xmlFileDownlocal(cbRmbBankMessageDtl.getFileName().trim());
		} catch (Exception e) {
			respCode = e.getMessage();
			logger.info("*********call BIS is error" + e);
		}
		return respCode;
	}

	/**
	 * 
	 * @Description: ftp文件下载到本地
	 * @param fileName
	 * @return
	 * @throws Exception
	 * @author
	 */
	private boolean xmlFileDownlocal(String fileName) throws Exception {
		FtpUtils ftp = new FtpUtils(cbrConfig.get("ftp.ip"), Integer.valueOf(cbrConfig.get("ftp.port")),
				cbrConfig.get("ftp.username"), cbrConfig.get("ftp.password"), cbrConfig.get("ftp.download.path"));

		String localFileName = cbrConfig.get("local.download.path") + fileName;
		logger.error("**** 下载文件名称：*****　" + fileName);
		return ftp.downFile(fileName, localFileName, CbRmbBankConstants.CHARSET_GBK);
	}

	/**
	 * 
	 * @Description: xml文件转换为string字符串
	 * @param fileName
	 * @return
	 * @throws Exception
	 * @author gd.cui
	 */
	private String xmlFileToString(String fileName) throws Exception {
		FtpUtils ftp = new FtpUtils(cbrConfig.get("ftp.ip"), Integer.valueOf(cbrConfig.get("ftp.port")),
				cbrConfig.get("ftp.username"), cbrConfig.get("ftp.password"), cbrConfig.get("ftp.download.path"));
		String localFileName = cbrConfig.get("local.download.path") + fileName;
		logger.error("**** ccb send file name*****　" + fileName);
		return ftp.readFile(fileName, localFileName, CbRmbBankConstants.CHARSET_GBK);
	}

	/**
	 * 
	 * @Description: 文件校验，并返回信息
	 * @param source
	 * @param notificationMsg
	 * @return
	 * @author gd.cui
	 */
	private CbRmbResponseMsg checkFile(byte[] source, CbRmbNotificationMsg notificationMsg) {
		CbRmbResponseMsg responseMsg = BeanMapper.map(notificationMsg, CbRmbResponseMsg.class);
		if (source != null && source.length >= CbRmbNotificationMsg.MSG_NOTIFICATION_LENGTH) {
			responseMsg.setRetCode(CbRmbBankConstants.SUCCESS);
			responseMsg.setRetMsg("查询请求接收成功");
		} else {
			responseMsg.setRetCode("900004");
			responseMsg.setRetMsg("HTTP请求错误，报文not enough");
		}
		return responseMsg;
	}

	public Map<String, String> getCbrConfig() {
		return cbrConfig;
	}

	public void setCbrConfig(Map<String, String> cbrConfig) {
		this.cbrConfig = cbrConfig;
	}

	@Override
	public String findCbRmbCcbResultByGopayOrderId(String goapayOrderId) throws GopayException {
		CbRmbBankOrderDtl bankOrder = cbRmbBankOrderDtlDao.findByGopayOrderId(goapayOrderId);
		if (bankOrder == null) {
			logger.error("findCbRmbCcbResultByGopayOrderId CbRmbBankOrderDtl 不存在" + goapayOrderId);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
		}
		if (CbRmbBankOrderState._03.value.equals(bankOrder.getState())) {
			logger.error("CbRmbBankOrderDtl 订单状态为03不能对账" + goapayOrderId);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E5042);
		}
		String hql = "from CbRmbBankMessageDtl t where t.orderMessageId=:orderMessageId";
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("orderMessageId", bankOrder.getOrderMessageId());
		List<CbRmbBankMessageDtl> messageDtls = cbRmbBankMessageDtlDao.findByHql(hql, param);
		if (messageDtls == null || messageDtls.size() != 1) {
			logger.error("CbRmbBankOrderDtl 订单状态数据异常不能对账" + goapayOrderId);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100F1002);
		}
		CbRmbBankMessageDtl message = messageDtls.get(0);
		CbRmbQueryReqMsg reqMsg = new CbRmbQueryReqMsg();
		reqMsg.setTranType(CbRmbBankConstants.QUERY_TRAN_TYPE);
		reqMsg.setSenderId(CbRmbBankConstants.QUERY_SENDER_ID);
		reqMsg.setTranSn(message.getTranSn());
		reqMsg.setMac(message.getMac());
		CbRmbQueryRespMsg respMsg = findCbRmbCcbResult(reqMsg);
		//if(respMsg!=null && CbRmbBankConstants.SUCCESS.equals(respMsg.getRetCode())){
		if(respMsg!=null){//TODO换成上边的
			CbRmbNotificationMsg notificationMsg=new CbRmbNotificationMsg();
			notificationMsg.setTranType("02");
			notificationMsg.setSenderId("CCBS");
			notificationMsg.setTranData(message.getTranData());
			notificationMsg.setTranTime(DateUtils.getCurrDate("HHmmss"));
			notificationMsg.setTranSn(message.getTranSn());
			notificationMsg.setMac(message.getMac());
			String fileName=message.getFileName().replace("KJZFLP", "KJZFHP");
			notificationMsg.setFileName(fileName);
			CbRmbResponseMsg responseMsg=checkFile(notificationMsg.getByteData(),notificationMsg);
			logger.info("bis manager query=============" + ReflectionToStringBuilder.toString(responseMsg));
			logger.info("bis manager query=============" + ReflectionToStringBuilder.toString(notificationMsg));
			return callBIS(notificationMsg, responseMsg);
		}
		return null;
	}

	@Override
	public CbRmbQueryRespMsg findCbRmbCcbResult(CbRmbQueryReqMsg reqMsg) throws GopayException {
		logger.info("=========this is bis manager query=============" + ReflectionToStringBuilder.toString(reqMsg));
		return cbRmbCcbBankServiceClient.findCbRmbCcbResult(reqMsg);
	}
}
